package org.zongf.learn.grpc;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author zongf
 * @since 2023-07-05
 **/
public class HelloThread {


    /*

    积分发放:
        按员工职位统一发放
            1. 多线程扫表
            2. 多线程执行发放记录
            3. 如果发放失败，则原地重试2次，如果依然失败，则将讲 user_id 和 points 写入到临时表
            4. 临时表数据人工处理积分发放

        导入 excel 方法
            1. 读取Excel 文件流为 List<Object> 对象， Object 包含 userId 和 points 字段
            2. 遍历List<Object>, 逐个用户发放积分
            3. 积分发放失败的 用户id 直接返回

        表结构
            t_user:  id, ... , points : 总积分

            t_user_point: id, user_id, points : 积分发放记录

            t_user_point_cost: id, user_id, order_id, points: 积分消费记录

            t_point_send: 积分发放临时表， id, user_id , points

     */

    public static void main(String[] args) throws Exception {

        // 从excel 读取用户id
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 20; i++) {
            list.add(i+1);
        }

        // 创建线程池: 固定线程池，线程池里面只有3个工作线程
        ExecutorService threadPool = Executors.newFixedThreadPool(10);

        // 原子变量控制游标/分页
        AtomicInteger curIdx = new AtomicInteger(0);

        // 线程任务
        Runnable givePointTask = new Runnable(){
            @Override
            public void run() {
                // 循环终止条件: 当游标到达列表尾部时，终止循环
                while (curIdx.get() < list.size()) {

                    // 执行发放积分动作

                    // 从数据库或者列表获取用户信息
                    Integer userId = list.get(curIdx.getAndIncrement());

                    // 计算用户应该发放的积分
                    Integer points = userId + 10;

                    // 发放积分
                    String log = String.format("[%s] 给用户 %s 发放 %s 积分", Thread.currentThread().getName(), userId, points);
                    System.out.println(log);
                }
            }
        };

        // 使用3个线程执行任务
        for (int i = 0; i < 7; i++) {
            threadPool.submit(givePointTask);
        }


    }



}
